home *** CD-ROM | disk | FTP | other *** search
- /*
- File: HIDEmulation.c
-
- Contains: HID Emulation glue code between the ADB SHIM and the USB Mouse HID Module
-
- Version: xxx put version here xxx
-
- Copyright: © 1998-1999 by Apple Computer, Inc., all rights reserved.
-
- */
-
- #include <Types.h>
- #include <Devices.h>
- #include <DriverServices.h>
- #include <CursorDevices.h>
- #include <USB.h>
- #include <MixedMode.h>
-
- #ifndef LMGetJADBProc
- #define LMGetJADBProc() (*((volatile UniversalProcPtr *)0x06B8))
- #endif
-
- #ifndef LMSetJADBProc
- #define LMSetJADBProc(value) ((*(UniversalProcPtr *)0x06B8) = (value))
- #endif
-
-
- #include "MouseModule.h"
-
- enum
- {
- uppJADBProcProcInfo = kRegisterBased
- | RESULT_SIZE(SIZE_CODE(sizeof(unsigned long)))
- | REGISTER_RESULT_LOCATION(kRegisterD0)
- | REGISTER_ROUTINE_PARAMETER(1, kRegisterD0, SIZE_CODE(sizeof(unsigned long)))
- };
-
- // an icky little struct that makes the world go around
-
- #pragma options align=mac68k
-
- typedef struct JADBProcGlueCode
- {
- UInt16 jsrLong;
- UniversalProcPtr ourJADBProc;
- UInt16 jmpLong;
- UniversalProcPtr oldJADBProc;
-
- // We want to flush the DR cache after we modify the above fields. However,
- // there does not seem to be any way to do this from PPC code. The only
- // real way to do this, is to copy this data structure onto itself. BlockMove
- // will flush the DR cache then. Of course, BlockMove will not flush the DR cache
- // for BlockMove's of less than 20 bytes. We need to pad our data structure out to be
- // > 20 bytes.
-
- UInt32 padForBlockMove[5];
- } JADBProcGlueCode;
-
- #pragma options align=reset
-
- static JADBProcGlueCode* gMouseJumpIsland;
-
- static UInt32 myMouseADBProc(UInt32 adbReInitState);
-
- RoutineDescriptor myMouseADBProcRD = BUILD_ROUTINE_DESCRIPTOR(uppJADBProcProcInfo, (ProcPtr) myMouseADBProc);
-
- extern usbMousePBStruct myMousePB;
-
- USBHIDRev2DispatchTable TheHIDModuleDispatchTable =
- {
- (UInt32)0,
- (USBHIDInstallInterruptProcPtr)USBHIDInstallInterrupt,
- (USBHIDPollDeviceProcPtr)USBHIDPollDevice,
- (USBHIDControlDeviceProcPtr)USBHIDControlDevice,
- (USBHIDGetDeviceInfoProcPtr)USBHIDGetDeviceInfo,
- (USBHIDEnterPolledModeProcPtr)USBHIDEnterPolledMode,
- (USBHIDExitPolledModeProcPtr)USBHIDExitPolledMode,
- (USBHIDInstallNotificationProcPtr)USBHIDInstallNotification
- };
-
- void USBMouseIn(UInt32 refcon, void * theData)
- {
- #pragma unused (refcon)
-
- USBHIDDataPtr pMouseData;
- static UInt16 oldbuttons = 0;
- UInt16 changedbuttons = 0;
-
- // DebugStr("\pIn USBMouseIn");
- pMouseData = (USBHIDDataPtr)theData;
-
- if (myMousePB.pCursorDeviceInfo) // don't call cursor device manager functions without a good cursor device
- {
- // Tell the Cursor Device Manager that we moved
- if ((pMouseData->mouse.XDelta != 0) || (pMouseData->mouse.YDelta !=0))
- {
- CursorDeviceMove(myMousePB.pCursorDeviceInfo, pMouseData->mouse.XDelta, pMouseData->mouse.YDelta);
- }
-
- // Update with the state of the buttons.
- pMouseData->mouse.buttons &= 0x07;
- changedbuttons = oldbuttons ^ pMouseData->mouse.buttons;
- if (changedbuttons)
- {
- CursorDeviceButtons(myMousePB.pCursorDeviceInfo, (short)pMouseData->mouse.buttons);
- }
- oldbuttons = pMouseData->mouse.buttons;
- }
- }
-
- OSStatus USBHIDInstallInterrupt(HIDInterruptProcPtr HIDInterruptFunction, UInt32 refcon)
- {
- USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Set interrupt pointer", (UInt32)HIDInterruptFunction);
- myMousePB.interruptRefcon = refcon;
-
- if (HIDInterruptFunction == USBMouseIn) // if someone is re-installing the USBMouseIn routine then this is
- { // an indication that someone earlier requested the interrupt
- myMousePB.pSHIMInterruptRoutine = nil; // pointer, saved it, and restored it. When the USBMouseIn
- USBHIDControlDevice(kHIDEnableDemoMode, 0); // routine is to be used, we've got to re-enable demo mode,
- // otherwise there won't be a cursor device manager entry for us...
- }
- else
- {
- USBHIDControlDevice(kHIDDisableDemoMode, 0); // disable demo mode
- myMousePB.pSHIMInterruptRoutine = HIDInterruptFunction;
- }
- return noErr;
- }
-
- OSStatus USBHIDInstallNotification(HIDNotificationProcPtr HIDNotification, UInt32 refcon)
- {
- USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Set notification proc ptr", (UInt32)HIDNotification);
- myMousePB.notificationRefcon = refcon;
-
- myMousePB.pNotificationRoutine = HIDNotification;
- return noErr;
- }
-
- OSStatus USBHIDPollDevice(void)
- {
- return kUSBInternalErr;
- }
-
- OSStatus USBHIDControlDevice(UInt32 theControlSelector, void * theControlData)
- {
- #pragma unused (theControlData)
-
- switch (theControlSelector)
- {
- case kHIDRemoveInterruptHandler:
- USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Removing interrupt handler!!!", myMousePB.interfaceRef);
- myMousePB.interruptRefcon = nil;
- myMousePB.pSavedInterruptRoutine = nil;
- myMousePB.pSHIMInterruptRoutine = nil;
- if (myMousePB.pCursorDeviceInfo != 0)
- {
- CursorDeviceDisposeDevice(myMousePB.pCursorDeviceInfo);
- myMousePB.pCursorDeviceInfo = 0;
- }
- break;
-
- case kHIDRemoveNotification:
- USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Removing notification!!!", myMousePB.interfaceRef);
- myMousePB.notificationRefcon = nil;
- myMousePB.pNotificationRoutine = NotifyRegisteredHIDUser;
- break;
-
- case kHIDEnableDemoMode:
- USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Demo Mode Enabled", myMousePB.interfaceRef);
-
- if (myMousePB.pCursorDeviceInfo == 0)
- {
- myMousePB.pCursorDeviceInfo = &myMousePB.cursorDeviceInfo;
- CursorDeviceNewDevice(&myMousePB.pCursorDeviceInfo);
-
- CursorDeviceSetAcceleration(myMousePB.pCursorDeviceInfo, (Fixed)(1<<16));
-
- CursorDeviceSetButtons(myMousePB.pCursorDeviceInfo, 3); // should actually be set by reading
- // the HID descriptor, but lacking
- // a parser, we'll just force it
- // this way.
- CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 0, kButtonSingleClick, 0L);
- CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 1, kButtonSingleClick, 0L);
- CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 2, kButtonSingleClick, 0L);
- CursorDeviceUnitsPerInch(myMousePB.pCursorDeviceInfo, (Fixed)(myMousePB.unitsPerInch));
-
- myMousePB.pSavedInterruptRoutine = myMousePB.pSHIMInterruptRoutine;
- myMousePB.pSHIMInterruptRoutine = USBMouseIn;
- }
- break;
-
- case kHIDDisableDemoMode:
- USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Demo Mode Disabled", myMousePB.interfaceRef);
- if (myMousePB.pCursorDeviceInfo != 0)
- {
- CursorDeviceDisposeDevice(myMousePB.pCursorDeviceInfo);
- myMousePB.pCursorDeviceInfo = 0;
- }
- myMousePB.pSHIMInterruptRoutine = myMousePB.pSavedInterruptRoutine;
- break;
-
- default:
- return paramErr;
- }
- return noErr;
- }
-
-
-
- OSStatus USBHIDGetDeviceInfo(UInt32 theInfoSelector, void * theInfo)
- {
- HIDInterruptProcPtr * pHIDIntProcPtr;
- UInt32 * pUnits;
- UInt32 * pInterruptRefcon;
-
- switch (theInfoSelector)
- {
- case kHIDGetDeviceUnitsPerInch:
- pUnits = (UInt32*)theInfo;
- *pUnits = (UInt32)(myMousePB.unitsPerInch);
- break;
-
- case kHIDGetInterruptHandler:
- USBExpertStatus(myMousePB.interfaceRef, kMouseModuleName": Get interrupt pointer", (UInt32)(myMousePB.pSHIMInterruptRoutine));
- pHIDIntProcPtr = (HIDInterruptProcPtr *)theInfo;
- *pHIDIntProcPtr = myMousePB.pSHIMInterruptRoutine;
- break;
-
- case kHIDGetInterruptRefcon:
- pInterruptRefcon = (UInt32 *)theInfo;
- *pInterruptRefcon = myMousePB.interruptRefcon;
- break;
-
- default:
- return paramErr;
- }
- return noErr;
- }
-
- OSStatus USBHIDEnterPolledMode(void)
- {
- return unimpErr;
- }
-
- OSStatus USBHIDExitPolledMode(void)
- {
- return unimpErr;
- }
-
- void NotifyRegisteredHIDUser(UInt32 refcon, UInt32 reportSize, void * theReport, USBReference theInterfaceRef)
- //void NotifyRegisteredHIDUser(UInt32 devicetype, UInt8 hidReport[])
- {
- #pragma unused (refcon)
- #pragma unused (reportSize)
- #pragma unused (theInterfaceRef)
-
- USBHIDData theMouseData;
- SInt8 myXDelta, myYDelta;
- char * hidReport;
-
- hidReport = (char *)theReport;
- theMouseData.mouse.buttons = (UInt16)hidReport[0];
-
- myXDelta = (SInt8)hidReport[1];
- myYDelta = (SInt8)hidReport[2];
-
- theMouseData.mouse.XDelta = (SInt16)myXDelta;
- theMouseData.mouse.YDelta = (SInt16)myYDelta;
- if (myMousePB.pSHIMInterruptRoutine)
- {
- (*myMousePB.pSHIMInterruptRoutine)(myMousePB.interruptRefcon, (void *)&theMouseData);
- }
- }
-
- static UInt32
- myMouseADBProc(UInt32 adbReInitState)
- {
-
- // adbReInitState = 0, just before the cursor device manager devices are removed.
- // adbReInitState = non-zero, after the devices are removed. This is when we need to
- // reinsert our device.
-
- if (adbReInitState == 0)
- {
- if (myMousePB.pCursorDeviceInfo != 0)
- {
- myMousePB.pCursorDeviceInfo = 0;
- }
- }
- else
- {
- if (myMousePB.pSHIMInterruptRoutine == USBMouseIn) // are we using our cursor device?
- {
- myMousePB.pCursorDeviceInfo = &myMousePB.cursorDeviceInfo;
- CursorDeviceNewDevice(&myMousePB.pCursorDeviceInfo);
-
- CursorDeviceSetAcceleration(myMousePB.pCursorDeviceInfo, (Fixed)(1<<16));
-
- CursorDeviceSetButtons(myMousePB.pCursorDeviceInfo, 3); // should actually be set by reading
- // the HID descriptor, but lacking
- // a parser, we'll just force it
- // this way.
- CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 0, kButtonSingleClick, 0L);
- CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 1, kButtonSingleClick, 0L);
- CursorDeviceButtonOp(myMousePB.pCursorDeviceInfo, 2, kButtonSingleClick, 0L);
- CursorDeviceUnitsPerInch(myMousePB.pCursorDeviceInfo, (Fixed)(myMousePB.unitsPerInch));
- }
- }
-
- return(adbReInitState);
- }
-
-
- void ChainJADBProc(void)
- {
- JADBProcGlueCode stackedBasedVersion;
-
- // Hook ourselves into JADBProc to be notified whenever ADBReInit gets called. As a
- // result of ADBReInit(), any CursorDevice records are deleted. So, we'll hook ourselves
- // into JADBProc, and recreate our CursorDevice record whenever ADBReInit has completed.
-
-
- if ((gMouseJumpIsland = (JADBProcGlueCode *) NewPtrSysClear(sizeof(JADBProcGlueCode))) == nil)
- {
- return; // just bail if we can't allocate any memory
- }
-
- stackedBasedVersion.jsrLong = 0x4EB9;
- stackedBasedVersion.ourJADBProc = &myMouseADBProcRD;
- stackedBasedVersion.jmpLong = 0x4EF9;
- stackedBasedVersion.oldJADBProc = LMGetJADBProc();
-
- // We want to flush the DR cache after we modify the above fields. However,
- // there does not seem to be any way to do this from PPC code. The only
- // real way to do this, is to copy this data structure onto itself. BlockMove
- // will flush the DR cache then. Of course, BlockMove will not flush the DR cache
- // for BlockMove's of less than 20 bytes. We need to pad our data structure out to be
- // > 20 bytes.
-
- BlockMove(&stackedBasedVersion, gMouseJumpIsland, sizeof(JADBProcGlueCode));
-
- LMSetJADBProc((UniversalProcPtr) gMouseJumpIsland);
- }
-
- void UnchainJADBProc(void)
- {
- JADBProcGlueCode stackedBasedVersion;
-
- // We cannot totally remove ourselves from the ADBReinit chain. Since someone might have patched
- // themselves into the JADBProc chain after us, we need to leave a small jump island pointing
- // to the person before us in the chain.
-
- // We want to flush the DR cache after we modify the above fields. However,
- // there does not seem to be any way to do this from PPC code. The only
- // real way to do this, is to copy this data structure onto itself. BlockMove
- // will flush the DR cache then. Of course, BlockMove will not flush the DR cache
- // for BlockMove's of less than 20 bytes. We need to pad our data structure out to be
- // > 20 bytes.
-
- BlockMove(gMouseJumpIsland, &stackedBasedVersion, sizeof(JADBProcGlueCode));
-
- stackedBasedVersion.jsrLong = 0x2048;
- stackedBasedVersion.ourJADBProc = (UniversalProcPtr) 0x20482048;
-
- BlockMove(&stackedBasedVersion, gMouseJumpIsland, sizeof(JADBProcGlueCode));
- }